package cosc617_blackteam;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.HashMap;
import java.util.Map;

/** Class to represent a food item in a Menu
 * @author Laura Semesky
 * 
 * edited by Anton on 4/12/2013 - replaced heartHealthy with specialAttributes for all methods in menuItem  
 */
public class MenuItem {
	private String name, category;
        private Map<MenuSpecialAttribute,String> specialAttributes;
	private ArrayList<String> ingredients;
	private BigDecimal price;
	private int minutesToCook;
	
	
        /**
	 * @param name Name of the Menu Item
	 * @param mainIngredient The main ingredient of the menu item
	 * @param priceString String representing the price of the MenuItem 
	 * (I read parsing strings is the most accurate way to represent price as a BigDecimal)
	 */
	public MenuItem(String name, ArrayList<String> ingredients, String category, String priceString){
		this.name = name;
		this.ingredients = ingredients;
		this.category = category;
		//this.heartHealthy = heartHealthy;
                this.specialAttributes = new HashMap<>();
		this.price = new BigDecimal(priceString);
	}
        public MenuItem(String name, ArrayList<String> ingredients, String category, String priceString, MenuSpecialAttribute[] specialAttributes, int minutesToCook){
		this.name = name;
		this.ingredients = ingredients;
		this.category = category;
                this.specialAttributes = new HashMap<>();
		this.price = new BigDecimal(priceString);
                this.addSpecialAttributes(specialAttributes);
        this.minutesToCook = minutesToCook;
	}
	
	/**
	 * @param i MenuItem to be compared to this MenuItem
	 * @return whether MenuItem i is equal to this MenuItem
	 */
	public boolean equals(MenuItem i){
		if(!this.name.equals(i.name))
			return false;
		
		//checks if all of this menu item's ingredients are contained in the given item's ingredients and then
		//if all of the given item's ingredients are in this item menu's ingredients.
		if(!i.ingredients.containsAll(this.ingredients)||!this.ingredients.containsAll(i.ingredients))
			return false;
		/*
		if(this.heartHealthy != i.heartHealthy)
			return false;
                */
                
                //this will return false if the specialAttribute values differ in case, but everything else is equal. just a heads up.
                if(!this.specialAttributes.equals(i.specialAttributes))
                {
                   return false;
                }
		
		//need to use compareTo to ignore scale differences
		if(this.price.compareTo(i.price) != 0)
			return false;
		
		if(!this.category.equals(i.category))
			return false;
		
		return true;
	}
	public BigDecimal getPrice() {
		return price;
	}

	public void setPrice(BigDecimal price) {
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}public int getPrepTime(){
		return minutesToCook;
	}

	public ArrayList<String> getIngredients() {
		return ingredients;
	}

	public void addIngredient(String newIngredient) {
		this.ingredients.add(newIngredient);
	}
        
        /**
         * @param key String to be used to check if the special attribute exists 
	 * @return whether the special attribute exists for the MenuItem with the provided key
         */
        public boolean hasSpecialAttribute(MenuSpecialAttribute key)
        {
           return this.specialAttributes.containsKey(key);
        }
        /**
         * @param key String to be used to check if the special attribute exists. Does not check if key exists. 
	 * @return the attribute that maps to the provided key
         */
        public String getSpecialAttribute(MenuSpecialAttribute key)
        {
          return this.specialAttributes.get(key); 
        }
        /**
         * @param key String to be used as a case-insensitive key
         * @param value String used for the public display of the special attribute in human readable format.
         */
        public void setSpecialAttribute(MenuSpecialAttribute key, String value)
        {
          this.specialAttributes.put(key, value);  
        }
         /**
         * @param values String[] used for the public display of the special attribute in human readable format. the value is converted into a corresponding key without spaces and lowercase.
         */
        public final void addSpecialAttributes(MenuSpecialAttribute[] values)
        {  if(values == null)
        	return;
           for(MenuSpecialAttribute value : values)
           {
              this.specialAttributes.put(value, value.toString());
           }
        }
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 * Format is Name (Ingredient) $price <HeartHealthy>
	 */
	public String toString(){
		final NumberFormat currencyInstance = NumberFormat.getCurrencyInstance(new Locale("en", "US"));
		String ingredientList = "";
		for(int i = 0; i < ingredients.size(); i++){
			ingredientList += ingredients.get(i);
			if(i < ingredients.size() - 1)
				 ingredientList += ", ";
		}
		String output = name  + " " + currencyInstance.format(price) + " ";
		/*
                if (heartHealthy)
			output += " <Heart Healthy>";
                 */       
                for(String specialAttribute : this.specialAttributes.values())
                {
                    output += " <" + specialAttribute + ">";
                }
                output += "\nIngredients: " + ingredientList;
		return output;
	}
        //MenuItem(String name, ArrayList<String> ingredients, String category, String priceString, String[] specialAttributes)
        public MenuItem copy()
        {
            ArrayList<String> ingredientsCopy = new ArrayList<>();
            int sasCount = this.specialAttributes.size();
            MenuSpecialAttribute[] specialAttributesCopy = new MenuSpecialAttribute[sasCount];
            for(String ingredientCopy : this.ingredients)
            {
              ingredientsCopy.add(ingredientCopy);  
            }
            for(int i = 0; i < sasCount;i++)
            {
              specialAttributesCopy[i] = (MenuSpecialAttribute)this.specialAttributes.keySet().toArray()[i];
            }
            return new MenuItem(this.name, ingredientsCopy, this.category, this.price.toString(), specialAttributesCopy, minutesToCook);                     
        }
}
